<!DOCTYPE html>
<html class="client-nojs vector-feature-night-mode-disabled vector-feature-language-in-header-enabled vector-feature-language-in-main-page-header-disabled vector-feature-page-tools-pinned-disabled vector-feature-toc-pinned-clientpref-1 vector-feature-main-menu-pinned-disabled vector-feature-limited-width-clientpref-1 vector-feature-limited-width-content-enabled vector-feature-custom-font-size-clientpref-1 vector-feature-appearance-pinned-clientpref-1 vector-sticky-header-enabled" lang="en" dir="ltr"><head>
<meta charset="UTF-8">
<title>Cache-oblivious algorithm</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="canonical" href="https://en.wikipedia.org/wiki/Cache-oblivious_algorithm"> <link href="./mw/ext.cite.styles.css" rel="stylesheet" type="text/css">
<link href="./mw/ext.math.styles.css" rel="stylesheet" type="text/css">
<link href="./mw/skins.vector.icons.css" rel="stylesheet" type="text/css">
<link href="./mw/skins.vector.search.codex.styles.css" rel="stylesheet" type="text/css">
<link href="./mw/skins.vector.styles.css" rel="stylesheet" type="text/css">
<link href="./mw/user.styles.css" rel="stylesheet" type="text/css">
<meta name="ResourceLoaderDynamicStyles" content="">
<link rel="stylesheet" type="text/css" href="./mw/site.styles.css">
<link rel="stylesheet" type="text/css" href="./mw/noscript.css">
<link rel="stylesheet" type="text/css" href="./footer.css">
<link rel="stylesheet" type="text/css" href="./vector-2022.css">
</head>
<body class="skin--responsive skin-vector skin-vector-search-vue mediawiki ltr sitedir-ltr mw-hide-empty-elt ns-0 ns-subject page-Cache-oblivious_algorithm rootpage-Cache-oblivious_algorithm skin-vector-2022 action-view">
<div class="mw-page-container">
<div class="mw-page-container-inner">
<div class="mw-content-container">
<main id="content" class="mw-body">
<header class="mw-body-header vector-page-titlebar">
<h1 id="firstHeading" class="firstHeading mw-first-heading">
<span id="openzim-page-title" class="mw-page-title-main"><span class="mw-page-title-main">Cache-oblivious algorithm</span></span>
</h1>
</header>
<a id="top"></a>
<div id="bodyContent" class="vector-body ve-init-mw-desktopArticleTarget-targetContainer" aria-labelledby="firstHeading" data-mw-ve-target-container="">
<div id="mw-content-text" class="mw-body-content mw-content-ltr" lang="en" dir="ltr"><div class="mw-content-ltr mw-parser-output" lang="en" dir="ltr">
<p>In <a href="Computing" title="Computing">computing</a>, a <b>cache-oblivious algorithm</b> (or cache-transcendent algorithm) is an <a href="Algorithm" title="Algorithm">algorithm</a> designed to take advantage of a processor <a href="CPU_cache" title="CPU cache">cache</a> without having the size of the cache (or the length of the <a href="Cache_line" class="mw-redirect" title="Cache line">cache lines</a>, etc.) as an explicit parameter. An <b>optimal cache-oblivious algorithm</b> is a cache-oblivious algorithm that uses the cache optimally (in an <a href="Asymptotic_notation" class="mw-redirect" title="Asymptotic notation">asymptotic</a> sense, ignoring constant factors). Thus, a cache-oblivious algorithm is designed to perform well, without modification, on multiple machines with different cache sizes, or for a <a href="Memory_hierarchy" title="Memory hierarchy">memory hierarchy</a> with different levels of cache having different sizes. Cache-oblivious algorithms are contrasted with explicit <i><a href="Loop_tiling" class="mw-redirect" title="Loop tiling">loop tiling</a></i>, which explicitly breaks a problem into blocks that are optimally sized for a given cache.
</p><p>Optimal cache-oblivious algorithms are known for <a href="Cache-oblivious_matrix_multiplication" class="mw-redirect" title="Cache-oblivious matrix multiplication">matrix multiplication</a>, <a href="Matrix_transposition" class="mw-redirect" title="Matrix transposition">matrix transposition</a>, <a href="Funnelsort" title="Funnelsort">sorting</a>, and several other problems. Some more general algorithms, such as <a href="Cooley%E2%80%93Tukey_FFT_algorithm" title="Cooley–Tukey FFT algorithm">Cooley–Tukey FFT</a>, are optimally cache-oblivious under certain choices of parameters. As these algorithms are only optimal in an asymptotic sense (ignoring constant factors), further machine-specific <a href="Performance_tuning" title="Performance tuning">tuning</a> may be required to obtain nearly optimal performance in an absolute sense. The goal of cache-oblivious algorithms is to reduce the amount of such tuning that is required.
</p><p>Typically, a cache-oblivious algorithm works by a <a href="Recursion" title="Recursion">recursive</a> <a href="Divide-and-conquer_algorithm" title="Divide-and-conquer algorithm">divide-and-conquer algorithm</a>, where the problem is divided into smaller and smaller subproblems. Eventually, one reaches a subproblem size that fits into the cache, regardless of the cache size. For example, an optimal cache-oblivious matrix multiplication is obtained by recursively dividing each matrix into four sub-matrices to be multiplied, multiplying the submatrices in a <a href="Depth-first" class="mw-redirect" title="Depth-first">depth-first</a> fashion. In tuning for a specific machine, one may use a <a href="Hybrid_algorithm" title="Hybrid algorithm">hybrid algorithm</a> which uses loop tiling tuned for the specific cache sizes at the bottom level but otherwise uses the cache-oblivious algorithm.
</p>
<meta property="mw:PageProp/toc">
<div class="mw-heading mw-heading2"><h2 id="History">History</h2></div>
<p>The idea (and name) for cache-oblivious algorithms was conceived by <a href="Charles_E._Leiserson" title="Charles E. Leiserson">Charles E. Leiserson</a> as early as 1996 and first published by <a href="Harald_Prokop" title="Harald Prokop">Harald Prokop</a> in his master's thesis at the <a href="Massachusetts_Institute_of_Technology" title="Massachusetts Institute of Technology">Massachusetts Institute of Technology</a> in 1999.<sup id="cite_ref-Prokop_1-0" class="reference"><a href="#cite_note-Prokop-1"><span class="cite-bracket">[</span>1<span class="cite-bracket">]</span></a></sup> There were many predecessors, typically analyzing specific problems; these are discussed in detail in Frigo et al. 1999. Early examples cited include Singleton 1969 for a recursive Fast Fourier Transform, similar ideas in Aggarwal et al. 1987, Frigo 1996 for matrix multiplication and LU decomposition, and Todd Veldhuizen 1996 for matrix algorithms in the <a href="Blitz%2B%2B" title="Blitz++">Blitz++</a> library.
</p>
<div class="mw-heading mw-heading2"><h2 id="Idealized_cache_model">Idealized cache model</h2></div>
<p>In general, a <a href="Computer_program" title="Computer program">program</a> can be made more cache-conscious:<sup id="cite_ref-nick05_2-0" class="reference"><a href="#cite_note-nick05-2"><span class="cite-bracket">[</span>2<span class="cite-bracket">]</span></a></sup>
</p>
<ul><li><i><a href="Locality_of_reference#Types_of_locality" title="Locality of reference">Temporal locality</a></i>, where the algorithm fetches the same pieces of memory multiple times;</li>
<li><i>Spatial locality</i>, where the subsequent memory accesses are adjacent or nearby <a href="Memory_address" title="Memory address">memory addresses</a>.</li></ul>
<p>Cache-oblivious algorithms are typically analyzed using an idealized model of the cache, sometimes called the <b>cache-oblivious model</b>. This model is much easier to analyze than a real cache's characteristics (which have complex associativity, replacement policies, etc.), but in many cases is provably within a constant factor of a more realistic cache's performance. It is different than the <a href="External_memory_model" class="mw-redirect" title="External memory model">external memory model</a> because cache-oblivious algorithms do not know the <a href="Block_(data_storage)" title="Block (data storage)">block size</a> or the <a href="Cache_(computing)" title="Cache (computing)">cache</a> size.
</p><p>In particular, the cache-oblivious model is an <a href="Abstract_machine" title="Abstract machine">abstract machine</a> (i.e., a theoretical <a href="Model_of_computation" title="Model of computation">model of computation</a>). It is similar to the <a href="RAM_model" class="mw-redirect" title="RAM model">RAM machine model</a> which replaces the <a href="Turing_machine" title="Turing machine">Turing machine</a>'s infinite tape with an infinite array. Each location within the array can be accessed in <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle O(1)}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>O</mi>
<mo stretchy="false">(</mo>
<mn>1</mn>
<mo stretchy="false">)</mo>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle O(1)}</annotation>
</semantics>
</math></span><img src="./e66384bc40452c5452f33563fe0e27e803b0cc21.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.838ex; width:4.745ex; height:2.843ex;" alt="{\displaystyle O(1)}" loading="lazy"></span> time, similar to the <a href="Random-access_memory" title="Random-access memory">random-access memory</a> on a real computer. Unlike the RAM machine model, it also introduces a cache: the second level of storage between the RAM and the CPU. The other differences between the two models are listed below. In the cache-oblivious model:
</p>
<ul><li>Memory is broken into blocks of <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle B}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>B</mi>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle B}</annotation>
</semantics>
</math></span><img src="./47136aad860d145f75f3eed3022df827cee94d7a.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.338ex; width:1.764ex; height:2.176ex;" alt="{\displaystyle B}" loading="lazy"></span> objects each.</li>
<li>A load or a store between <a href="Main_memory" class="mw-redirect" title="Main memory">main memory</a> and a CPU register may now be serviced from the cache.</li>
<li>If a load or a store cannot be serviced from the cache, it is called a <i>cache miss</i>.</li>
<li>A cache miss results in one block being loaded from the main memory into the cache. Namely, if the CPU tries to access word <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle w}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>w</mi>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle w}</annotation>
</semantics>
</math></span><img src="./88b1e0c8e1be5ebe69d18a8010676fa42d7961e6.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.338ex; width:1.664ex; height:1.676ex;" alt="{\displaystyle w}" loading="lazy"></span> and <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle x}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>x</mi>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle x}</annotation>
</semantics>
</math></span><img src="./87f9e315fd7e2ba406057a97300593c4802b53e4.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.338ex; width:1.33ex; height:1.676ex;" alt="{\displaystyle x}" loading="lazy"></span> is the line containing <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle w}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>w</mi>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle w}</annotation>
</semantics>
</math></span><img src="./88b1e0c8e1be5ebe69d18a8010676fa42d7961e6.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.338ex; width:1.664ex; height:1.676ex;" alt="{\displaystyle w}" loading="lazy"></span>, then <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle x}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>x</mi>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle x}</annotation>
</semantics>
</math></span><img src="./87f9e315fd7e2ba406057a97300593c4802b53e4.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.338ex; width:1.33ex; height:1.676ex;" alt="{\displaystyle x}" loading="lazy"></span> is loaded into the cache. If the cache was previously full, then a line will be evicted as well (see replacement policy below).</li>
<li>The cache holds <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle M}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>M</mi>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle M}</annotation>
</semantics>
</math></span><img src="./f82cade9898ced02fdd08712e5f0c0151758a0dd.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.338ex; width:2.442ex; height:2.176ex;" alt="{\displaystyle M}" loading="lazy"></span> objects, where <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle M=\Omega (B^{2})}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>M</mi>
<mo>=</mo>
<mi mathvariant="normal">Ω<!-- Ω --></mi>
<mo stretchy="false">(</mo>
<msup>
<mi>B</mi>
<mrow class="MJX-TeXAtom-ORD">
<mn>2</mn>
</mrow>
</msup>
<mo stretchy="false">)</mo>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle M=\Omega (B^{2})}</annotation>
</semantics>
</math></span><img src="./d4da530f0265309181bcc8b7f23396d4e90973af.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.838ex; width:11.846ex; height:3.176ex;" alt="{\displaystyle M=\Omega (B^{2})}" loading="lazy"></span>. This is also known as the <i>tall cache assumption</i>.</li>
<li>The cache is fully associative: each line can be loaded into any location in the cache.<sup id="cite_ref-Kumar_3-0" class="reference"><a href="#cite_note-Kumar-3"><span class="cite-bracket">[</span>3<span class="cite-bracket">]</span></a></sup></li>
<li>The replacement policy is optimal. In other words, the cache is assumed to be given the entire sequence of memory accesses during algorithm execution. If it needs to evict a line at time <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle t}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>t</mi>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle t}</annotation>
</semantics>
</math></span><img src="./65658b7b223af9e1acc877d848888ecdb4466560.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.338ex; width:0.84ex; height:2.009ex;" alt="{\displaystyle t}" loading="lazy"></span>, it will look into its sequence of future requests and evict the line whose first access is furthest in the future. This can be emulated in practice with the <a href="Least_Recently_Used" class="mw-redirect" title="Least Recently Used">Least Recently Used</a> policy, which is shown to be within a small constant factor of the offline optimal replacement strategy<sup id="cite_ref-Frigo99_4-0" class="reference"><a href="#cite_note-Frigo99-4"><span class="cite-bracket">[</span>4<span class="cite-bracket">]</span></a></sup><sup id="cite_ref-Sleator_5-0" class="reference"><a href="#cite_note-Sleator-5"><span class="cite-bracket">[</span>5<span class="cite-bracket">]</span></a></sup></li></ul>
<p>To measure the complexity of an algorithm that executes within the cache-oblivious model, we measure the number of <a href="Cache_miss" class="mw-redirect" title="Cache miss">cache misses</a> that the algorithm experiences. Because the model captures the fact that accessing elements in the <a href="Cache_(computing)" title="Cache (computing)">cache</a> is much faster than accessing things in <a href="Main_memory" class="mw-redirect" title="Main memory">main memory</a>, the <a href="Running_time" class="mw-redirect" title="Running time">running time</a> of the algorithm is defined only by the number of memory transfers between the cache and main memory. This is similar to the <a href="External_memory_model" class="mw-redirect" title="External memory model">external memory model</a>, which all of the features above, but cache-oblivious algorithms are independent of cache parameters (<span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle B}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>B</mi>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle B}</annotation>
</semantics>
</math></span><img src="./47136aad860d145f75f3eed3022df827cee94d7a.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.338ex; width:1.764ex; height:2.176ex;" alt="{\displaystyle B}" loading="lazy"></span> and <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle M}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>M</mi>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle M}</annotation>
</semantics>
</math></span><img src="./f82cade9898ced02fdd08712e5f0c0151758a0dd.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.338ex; width:2.442ex; height:2.176ex;" alt="{\displaystyle M}" loading="lazy"></span>).<sup id="cite_ref-Demaine02_6-0" class="reference"><a href="#cite_note-Demaine02-6"><span class="cite-bracket">[</span>6<span class="cite-bracket">]</span></a></sup> The benefit of such an algorithm is that what is efficient on a cache-oblivious machine is likely to be efficient across many real machines without fine-tuning for particular real machine parameters. For many problems, an optimal cache-oblivious algorithm will also be optimal for a machine with more than two <a href="Memory_hierarchy" title="Memory hierarchy">memory hierarchy</a> levels.<sup id="cite_ref-Frigo99_4-1" class="reference"><a href="#cite_note-Frigo99-4"><span class="cite-bracket">[</span>4<span class="cite-bracket">]</span></a></sup>
</p>
<div class="mw-heading mw-heading2"><h2 id="Examples">Examples</h2></div>
<p>The simplest cache-oblivious algorithm presented in Frigo et al. is an out-of-place <a href="Matrix_transpose" class="mw-redirect" title="Matrix transpose">matrix transpose</a> operation (<a href="In-place_matrix_transposition" title="In-place matrix transposition">in-place algorithms</a> have also been devised for transposition, but are much more complex for non-square matrices). Given <i>m</i>×<i>n</i> array <b>A</b> and <i>n</i>×<i>m</i> array <b>B</b>, we would like to store the transpose of <span class="texhtml mvar" style="font-style:italic;">A</span> in <span class="texhtml mvar" style="font-style:italic;">B</span>. The naive solution traverses one array in row-major order and another in column-major. The result is that when the matrices are large, we get a cache miss on every step of the column-wise traversal. The total number of cache misses is <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle \Theta (mn)}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi mathvariant="normal">Θ<!-- Θ --></mi>
<mo stretchy="false">(</mo>
<mi>m</mi>
<mi>n</mi>
<mo stretchy="false">)</mo>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle \Theta (mn)}</annotation>
</semantics>
</math></span><img src="./3869811594f411c0d4025ba7b8e5f8069b436cf4.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.838ex; width:7.053ex; height:2.843ex;" alt="{\displaystyle \Theta (mn)}" loading="lazy"></span>.
</p>
<p>The cache-oblivious algorithm has optimal work complexity <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle O(mn)}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>O</mi>
<mo stretchy="false">(</mo>
<mi>m</mi>
<mi>n</mi>
<mo stretchy="false">)</mo>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle O(mn)}</annotation>
</semantics>
</math></span><img src="./89ea09572a098b4762141a22c43a7ba1c20051cf.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.838ex; width:7.018ex; height:2.843ex;" alt="{\displaystyle O(mn)}" loading="lazy"></span> and optimal cache complexity <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle O(1+mn/B)}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>O</mi>
<mo stretchy="false">(</mo>
<mn>1</mn>
<mo>+</mo>
<mi>m</mi>
<mi>n</mi>
<mrow class="MJX-TeXAtom-ORD">
<mo>/</mo>
</mrow>
<mi>B</mi>
<mo stretchy="false">)</mo>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle O(1+mn/B)}</annotation>
</semantics>
</math></span><img src="./1fce18c6ce32ba203ab12883c1d6a15e17eccc5a.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.838ex; width:13.947ex; height:2.843ex;" alt="{\displaystyle O(1+mn/B)}" loading="lazy"></span>. The basic idea is to reduce the transpose of two large matrices into the transpose of small (sub)matrices. We do this by dividing the matrices in half along their larger dimension until we just have to perform the transpose of a matrix that will fit into the cache. Because the cache size is not known to the algorithm, the matrices will continue to be divided recursively even after this point, but these further subdivisions will be in cache. Once the dimensions <span class="texhtml mvar" style="font-style:italic;">m</span> and <span class="texhtml mvar" style="font-style:italic;">n</span> are small enough so an <i>input</i> array of size <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle m\times n}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>m</mi>
<mo>×<!-- × --></mo>
<mi>n</mi>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle m\times n}</annotation>
</semantics>
</math></span><img src="./12b23d207d23dd430b93320539abbb0bde84870d.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.338ex; width:6.276ex; height:1.676ex;" alt="{\displaystyle m\times n}" loading="lazy"></span> and an output array of size <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle n\times m}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>n</mi>
<mo>×<!-- × --></mo>
<mi>m</mi>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle n\times m}</annotation>
</semantics>
</math></span><img src="./d82325a2a02ad79bc7c347ba9702ad46eb0de824.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.338ex; width:6.276ex; height:1.676ex;" alt="{\displaystyle n\times m}" loading="lazy"></span> fit into the cache, both row-major and column-major traversals result in <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle O(mn)}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>O</mi>
<mo stretchy="false">(</mo>
<mi>m</mi>
<mi>n</mi>
<mo stretchy="false">)</mo>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle O(mn)}</annotation>
</semantics>
</math></span><img src="./89ea09572a098b4762141a22c43a7ba1c20051cf.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.838ex; width:7.018ex; height:2.843ex;" alt="{\displaystyle O(mn)}" loading="lazy"></span> work and <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle O(mn/B)}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>O</mi>
<mo stretchy="false">(</mo>
<mi>m</mi>
<mi>n</mi>
<mrow class="MJX-TeXAtom-ORD">
<mo>/</mo>
</mrow>
<mi>B</mi>
<mo stretchy="false">)</mo>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle O(mn/B)}</annotation>
</semantics>
</math></span><img src="./7367d86cb3534e5f7c6699be93f0f3b99a324b09.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.838ex; width:9.944ex; height:2.843ex;" alt="{\displaystyle O(mn/B)}" loading="lazy"></span> cache misses. By using this divide and conquer approach we can achieve the same level of complexity for the overall matrix.
</p><p>(In principle, one could continue dividing the matrices until a base case of size 1×1 is reached, but in practice one uses a larger base case (e.g. 16×16) in order to <a href="Amortized_analysis" title="Amortized analysis">amortize</a> the overhead of the recursive subroutine calls.)
</p><p>Most cache-oblivious algorithms rely on a divide-and-conquer approach. They reduce the problem, so that it eventually fits in cache no matter how small the cache is, and end the recursion at some small size determined by the function-call overhead and similar cache-unrelated optimizations, and then use some cache-efficient access pattern to merge the results of these small, solved problems.
</p><p>Like <a href="External_sorting" title="External sorting">external sorting</a> in the <a href="External_memory_model" class="mw-redirect" title="External memory model">external memory model</a>, cache-oblivious sorting is possible in two variants: <a href="Funnelsort" title="Funnelsort">funnelsort</a>, which resembles <a href="Mergesort" class="mw-redirect" title="Mergesort">mergesort</a>; and <a href="Cache-oblivious_distribution_sort" title="Cache-oblivious distribution sort">cache-oblivious distribution sort</a>, which resembles <a href="Quicksort" title="Quicksort">quicksort</a>. Like their external memory counterparts, both achieve a <a href="Running_time" class="mw-redirect" title="Running time">running time</a> of <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle O\left({\tfrac {N}{B}}\log _{\tfrac {M}{B}}{\tfrac {N}{B}}\right)}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>O</mi>
<mrow>
<mo>(</mo>
<mrow>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="false" scriptlevel="0">
<mfrac>
<mi>N</mi>
<mi>B</mi>
</mfrac>
</mstyle>
</mrow>
<msub>
<mi>log</mi>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="false" scriptlevel="0">
<mfrac>
<mi>M</mi>
<mi>B</mi>
</mfrac>
</mstyle>
</mrow>
</msub>
<mo><!-- --></mo>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="false" scriptlevel="0">
<mfrac>
<mi>N</mi>
<mi>B</mi>
</mfrac>
</mstyle>
</mrow>
</mrow>
<mo>)</mo>
</mrow>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle O\left({\tfrac {N}{B}}\log _{\tfrac {M}{B}}{\tfrac {N}{B}}\right)}</annotation>
</semantics>
</math></span><img src="./496ff85a291f2a81b89ac3b14929c774ad5c0035.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -2.671ex; width:16.713ex; height:6.343ex;" alt="{\displaystyle O\left({\tfrac {N}{B}}\log _{\tfrac {M}{B}}{\tfrac {N}{B}}\right)}" loading="lazy"></span>, which matches a <a href="Lower_bound" class="mw-redirect" title="Lower bound">lower bound</a> and is thus <a href="Asymptotically_optimal" class="mw-redirect" title="Asymptotically optimal">asymptotically optimal</a>.<sup id="cite_ref-Demaine02_6-1" class="reference"><a href="#cite_note-Demaine02-6"><span class="cite-bracket">[</span>6<span class="cite-bracket">]</span></a></sup>
</p>
<div class="mw-heading mw-heading2"><h2 id="Practicality">Practicality</h2></div>
<p>An empirical comparison of 2 RAM-based, 1 cache-aware, and 2 cache-oblivious algorithms implementing <a href="Priority_queue" title="Priority queue">priority queues</a> found that:<sup id="cite_ref-7" class="reference"><a href="#cite_note-7"><span class="cite-bracket">[</span>7<span class="cite-bracket">]</span></a></sup>
</p>
<ul><li>Cache-oblivious algorithms performed worse than RAM-based and cache-aware algorithms when data fits into main memory.</li>
<li>The cache-aware algorithm did not seem significantly more complex to implement than the cache-oblivious algorithms, and offered the best performance in all cases tested in the study.</li>
<li>Cache oblivious algorithms outperformed RAM-based algorithms when data size exceeded the size of main memory.</li></ul>
<p>Another study compared <a href="Hash_table" title="Hash table">hash tables</a> (as RAM-based or cache-unaware), <a href="B-tree" title="B-tree">B-trees</a> (as cache-aware), and a cache-oblivious data structure referred to as a "Bender set". For both execution time and memory usage, the hash table was best, followed by the B-tree, with the Bender set the worst in all cases. The memory usage for all tests did not exceed main memory. The hash tables were described as easy to implement, while the Bender set "required a greater amount of effort to implement correctly".<sup id="cite_ref-8" class="reference"><a href="#cite_note-8"><span class="cite-bracket">[</span>8<span class="cite-bracket">]</span></a></sup>
</p>
<div class="mw-heading mw-heading2"><h2 id="See_also">See also</h2></div>
<ul><li><a href="Cache-oblivious_distribution_sort" title="Cache-oblivious distribution sort">Cache-oblivious distribution sort</a></li>
<li><a href="External_memory_algorithm" title="External memory algorithm">External memory algorithm</a></li>
<li><a href="Funnelsort" title="Funnelsort">Funnelsort</a></li></ul>
<div class="mw-heading mw-heading2"><h2 id="References">References</h2></div>
<style data-mw-deduplicate="TemplateStyles:r1239543626">
/* start https://en.wikipedia.org/ */
.mw-parser-output .reflist{margin-bottom:0.5em;list-style-type:decimal}@media screen{.mw-parser-output .reflist{font-size:90%}}.mw-parser-output .reflist .references{font-size:100%;margin-bottom:0;list-style-type:inherit}.mw-parser-output .reflist-columns-2{column-width:30em}.mw-parser-output .reflist-columns-3{column-width:25em}.mw-parser-output .reflist-columns{margin-top:0.3em}.mw-parser-output .reflist-columns ol{margin-top:0}.mw-parser-output .reflist-columns li{page-break-inside:avoid;break-inside:avoid-column}.mw-parser-output .reflist-upper-alpha{list-style-type:upper-alpha}.mw-parser-output .reflist-upper-roman{list-style-type:upper-roman}.mw-parser-output .reflist-lower-alpha{list-style-type:lower-alpha}.mw-parser-output .reflist-lower-greek{list-style-type:lower-greek}.mw-parser-output .reflist-lower-roman{list-style-type:lower-roman}
/* end https://en.wikipedia.org/ */
</style><div class="reflist">
<div class="mw-references-wrap"><ol class="references">
<li id="cite_note-Prokop-1"><span class="mw-cite-backlink"><b><a href="#cite_ref-Prokop_1-0">^</a></b></span> <span class="reference-text">Harald Prokop. <a rel="nofollow" class="external text" href="http://supertech.csail.mit.edu/papers/Prokop99.pdf">Cache-Oblivious Algorithms</a>. Masters thesis, MIT. 1999.</span>
</li>
<li id="cite_note-nick05-2"><span class="mw-cite-backlink"><b><a href="#cite_ref-nick05_2-0">^</a></b></span> <span class="reference-text"><style data-mw-deduplicate="TemplateStyles:r1238218222">
/* start https://en.wikipedia.org/ */
.mw-parser-output cite.citation{font-style:inherit;word-wrap:break-word}.mw-parser-output .citation q{quotes:"\"""\"""'""'"}.mw-parser-output .citation:target{background-color:rgba(0,127,255,0.133)}.mw-parser-output .id-lock-free.id-lock-free a{background:url("./mw/Lock-green.svg")right 0.1em center/9px no-repeat}.mw-parser-output .id-lock-limited.id-lock-limited a,.mw-parser-output .id-lock-registration.id-lock-registration a{background:url("./mw/Lock-gray-alt-2.svg")right 0.1em center/9px no-repeat}.mw-parser-output .id-lock-subscription.id-lock-subscription a{background:url("./mw/Lock-red-alt-2.svg")right 0.1em center/9px no-repeat}.mw-parser-output .cs1-ws-icon a{background:url("./mw/Wikisource-logo.svg")right 0.1em center/12px no-repeat}body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .id-lock-free a,body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .id-lock-limited a,body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .id-lock-registration a,body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .id-lock-subscription a,body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .cs1-ws-icon a{background-size:contain;padding:0 1em 0 0}.mw-parser-output .cs1-code{color:inherit;background:inherit;border:none;padding:inherit}.mw-parser-output .cs1-hidden-error{display:none;color:var(--color-error,#d33)}.mw-parser-output .cs1-visible-error{color:var(--color-error,#d33)}.mw-parser-output .cs1-maint{display:none;color:#085;margin-left:0.3em}.mw-parser-output .cs1-kern-left{padding-left:0.2em}.mw-parser-output .cs1-kern-right{padding-right:0.2em}.mw-parser-output .citation .mw-selflink{font-weight:inherit}@media screen{.mw-parser-output .cs1-format{font-size:95%}html.skin-theme-clientpref-night .mw-parser-output .cs1-maint{color:#18911f}}@media screen and (prefers-color-scheme:dark){html.skin-theme-clientpref-os .mw-parser-output .cs1-maint{color:#18911f}}
/* end https://en.wikipedia.org/ */
</style><cite id="CITEREFAskitisZobel2005" class="citation book cs1">Askitis, Nikolas; Zobel, Justin (2005). <a rel="nofollow" class="external text" href="https://link.springer.com/chapter/10.1007/11575832_11">"Enhanced Byte Codes with Restricted Prefix Properties"</a>. <i>String Processing and Information Retrieval</i>. Lecture Notes in Computer Science. Vol. 3772. <a href="Springer_Publishing" title="Springer Publishing">Springer</a>. p. 93. <a href="Doi_(identifier)" class="mw-redirect" title="Doi (identifier)">doi</a>:<a rel="nofollow" class="external text" href="https://doi.org/10.1007%2F11575832_1">10.1007/11575832_1</a>. <a href="ISBN_(identifier)" class="mw-redirect" title="ISBN (identifier)">ISBN</a> <bdi>978-3-540-29740-6</bdi>.</cite> <span class="cs1-visible-error citation-comment"><code class="cs1-code">{{cite book}}</code>: </span><span class="cs1-visible-error citation-comment"><code class="cs1-code">|journal=</code> ignored (help)</span></span>
</li>
<li id="cite_note-Kumar-3"><span class="mw-cite-backlink"><b><a href="#cite_ref-Kumar_3-0">^</a></b></span> <span class="reference-text"><cite id="CITEREFKumar" class="citation journal cs1">Kumar, Piyush. "Cache-Oblivious Algorithms". <i>Algorithms for Memory Hierarchies</i>. LNCS 2625. Springer Verlag: <span class="nowrap">193–</span>212. <a href="CiteSeerX_(identifier)" class="mw-redirect" title="CiteSeerX (identifier)">CiteSeerX</a> <span class="id-lock-free" title="Freely accessible"><a rel="nofollow" class="external text" href="https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.150.5426">10.1.1.150.5426</a></span>.</cite></span>
</li>
<li id="cite_note-Frigo99-4"><span class="mw-cite-backlink">^ <a href="#cite_ref-Frigo99_4-0"><sup><i><b>a</b></i></sup></a> <a href="#cite_ref-Frigo99_4-1"><sup><i><b>b</b></i></sup></a></span> <span class="reference-text"><cite id="CITEREFFrigoLeisersonProkopRamachandran1999" class="citation conference cs1">Frigo, M.; <a href="Charles_Leiserson" class="mw-redirect" title="Charles Leiserson">Leiserson, C. E.</a>; <a href="Harald_Prokop" title="Harald Prokop">Prokop, H.</a>; Ramachandran, S. (1999). <a rel="nofollow" class="external text" href="http://supertech.csail.mit.edu/papers/FrigoLePr99.pdf"><i>Cache-oblivious algorithms</i></a> <span class="cs1-format">(PDF)</span>. Proc. IEEE Symp. on Foundations of Computer Science (FOCS). pp. <span class="nowrap">285–</span>297.</cite></span>
</li>
<li id="cite_note-Sleator-5"><span class="mw-cite-backlink"><b><a href="#cite_ref-Sleator_5-0">^</a></b></span> <span class="reference-text">Daniel Sleator, Robert Tarjan. <a rel="nofollow" class="external text" href="https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.367.6317&rep=rep1&type=pdf">Amortized Efficiency of List Update and Paging Rules</a>. In <i>Communications of the ACM</i>, Volume 28, Number 2, pp. 202–208. Feb 1985.</span>
</li>
<li id="cite_note-Demaine02-6"><span class="mw-cite-backlink">^ <a href="#cite_ref-Demaine02_6-0"><sup><i><b>a</b></i></sup></a> <a href="#cite_ref-Demaine02_6-1"><sup><i><b>b</b></i></sup></a></span> <span class="reference-text"><a href="Erik_Demaine" title="Erik Demaine">Erik Demaine</a>. <a rel="nofollow" class="external text" href="http://erikdemaine.org/papers/BRICS2002/">Cache-Oblivious Algorithms and Data Structures</a>, in Lecture Notes from the EEF Summer School on Massive Data Sets, BRICS, University of Aarhus, Denmark, June 27–July 1, 2002.</span>
</li>
<li id="cite_note-7"><span class="mw-cite-backlink"><b><a href="#cite_ref-7">^</a></b></span> <span class="reference-text"><cite id="CITEREFOlsenSkov2002" class="citation thesis cs1">Olsen, Jesper Holm; Skov, Søren Christian (2 December 2002). <a rel="nofollow" class="external text" href="http://hjemmesider.diku.dk/~jyrki/PE-lab/Publications/olsen-skov02.pdf"><i>Cache-Oblivious Algorithms in Practice</i></a> <span class="cs1-format">(PDF)</span> (Master's). University of Copenhagen<span class="reference-accessdate">. Retrieved <span class="nowrap">3 January</span> 2022</span>.</cite></span>
</li>
<li id="cite_note-8"><span class="mw-cite-backlink"><b><a href="#cite_ref-8">^</a></b></span> <span class="reference-text"><cite id="CITEREFVerver2008" class="citation web cs1">Verver, Maks (23 June 2008). <a rel="nofollow" class="external text" href="https://fmt.ewi.utwente.nl/media/61.pdf">"Evaluation of a Cache-Oblivious Data Structure"</a> <span class="cs1-format">(PDF)</span><span class="reference-accessdate">. Retrieved <span class="nowrap">3 January</span> 2022</span>.</cite></span>
</li>
</ol></div></div></div><!--htdig_noindex--><div><div class="zim-footer">
This article is issued from <a class="external text" title="Last edited on 2024-11-03" href="https://en.wikipedia.org/wiki/?title=Cache-oblivious_algorithm&oldid=1255108940">Wikipedia</a>. The text is available under <a class="external text" href="https://creativecommons.org/licenses/by-sa/4.0/deed.en">Creative Commons Attribution-Share Alike 4.0</a> unless otherwise noted. Additional terms may apply for the media files.
</div>
</div><!--/htdig_noindex--></div>
</div>
</main>
</div>
</div>
</div>
</body></html>